﻿/////////////////////////////////////////////////////////////////
//
// Silverlight 5: 3D Physics using Balder and Jiglibx
// by Andy Beaulieu - http://www.andybeaulieu.com
//
// LICENSE: This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ANY 
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS
// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
/////////////////////////////////////////////////////////////////
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Xna.Framework;
using System.Windows.Media.Imaging;

namespace Spritehand.Physics3D
{
    public class Utils
    {
        const float _terrainBumpiness = 15;

        public static Microsoft.Xna.Framework.Vector3 VectorBalderToXna(Balder.Math.Coordinate vector3)
        {
            return new Microsoft.Xna.Framework.Vector3((float)vector3.X, (float)vector3.Y, (float)vector3.Z);
        }

        public static Balder.Math.Coordinate VectorXnaToBalder(Microsoft.Xna.Framework.Vector3 vector3)
        {
            return new Balder.Math.Coordinate(Convert.ToDouble(vector3.X), Convert.ToDouble(vector3.Y), Convert.ToDouble(vector3.Z));
        }

        public static Balder.Math.Matrix MatrixXnaToBalder(Microsoft.Xna.Framework.Matrix matrixSrc)
        {
            Balder.Math.Matrix matrix = new Balder.Math.Matrix();

            matrix.M11 = matrixSrc.M11;
            matrix.M12 = matrixSrc.M12;
            matrix.M13 = matrixSrc.M13;
            matrix.M14 = matrixSrc.M14;
            matrix.M21 = matrixSrc.M21;
            matrix.M22 = matrixSrc.M22;
            matrix.M23 = matrixSrc.M23;
            matrix.M24 = matrixSrc.M24;
            matrix.M31 = matrixSrc.M31;
            matrix.M32 = matrixSrc.M32;
            matrix.M33 = matrixSrc.M33;
            matrix.M34 = matrixSrc.M34;
            matrix.M41 = matrixSrc.M41;
            matrix.M42 = matrixSrc.M42;
            matrix.M43 = matrixSrc.M43;
            matrix.M44 = matrixSrc.M44;

            return matrix;
        }

        /// <summary>
        /// Given an Image control with content, this method extracts the height map data
        /// from the image based on pixel "brightness" - that is, darker pixels are a lower
        /// height value.
        /// </summary>
        public static HeightMapInfo GetHeightMapInfo(Image terrain)
        {

            WriteableBitmap wb = new WriteableBitmap(terrain, new TranslateTransform());

            float terrainScale = 1;
            int width = wb.PixelWidth;
            int height = wb.PixelHeight;
            float[,] heights = new float[width, height];

            int offset = 0;
            for (int x = 0; x < width; x++)
            {
                for (int z = 0; z < height; z++)
                {
                    int thisX = Convert.ToInt32( terrainScale * (x - ((width - 1) / 2.0f)));
                    int thisZ = Convert.ToInt32(terrainScale * (z - ((height - 1) / 2.0f)));

                    float valueHeight = (PixelToValue(wb.Pixels[offset])) * _terrainBumpiness; ;

                    heights[x, z] = valueHeight;
                    offset++;
                }
            }
            return new HeightMapInfo(heights, terrainScale);
        }

        /// <summary>
        /// Returns the "height" value of a pixel based on its relative brightness.
        /// Useful for creating heightmaps from pixel values.
        /// </summary>
        public static float PixelToValue(int pixel)
        {
            byte B = (byte)(pixel & 0xFF); pixel >>= 8;
            byte G = (byte)(pixel & 0xFF); pixel >>= 8;
            byte R = (byte)(pixel & 0xFF); pixel >>= 8;
            byte A = (byte)(pixel);

            int total = (B + G + R);
            return (float)total / 765;
        }





    }
}
